using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using TrueVision3D;
using DxVBLibA;

namespace Goblin2
{
    // Manhattanville's code for loading buildings
    public partial class Manhattanville
    {
        // The View's per-building data loader "building_info.txt"
        public void loadBuildingInfo()
        {
            buildingInfo = new Hashtable();
            Hashtable type_ht = new Hashtable(), data_ht = new Hashtable(), values_ht = new Hashtable();
            FileStream bi_input = new FileStream("building_info.txt", FileMode.Open, FileAccess.Read);
            StreamReader sr = new StreamReader(bi_input);
            char[] splitter = { '\t' };
            string[] headings = sr.ReadLine().Trim().Split(splitter);
            string[] types = sr.ReadLine().Trim().Split(splitter);

            for (int i = 0; i < headings.Length; i++)
            {
                type_ht.Add(headings[i], types[i]);
                values_ht.Add(headings[i], new Hashtable());
            }

            while (!sr.EndOfStream)
            {
                string[] data_elements = sr.ReadLine().Trim().Split(splitter);
                Hashtable new_building = new Hashtable();

                for (int i = 0; i < headings.Length; i++)
                {
                    data_elements[i] = data_elements[i].Replace("\n", "").Replace("\r", "");
                    new_building.Add(headings[i], data_elements[i]);
                    if (!((Hashtable)values_ht[headings[i]]).ContainsKey(data_elements[i]))
                        ((Hashtable)values_ht[headings[i]]).Add(data_elements[i], "exists");
                }
                data_ht.Add(data_elements[0], new_building);
            }

            buildingInfo.Add("TYPES", type_ht);
            buildingInfo.Add("DATA", data_ht);
            buildingInfo.Add("VALUES", values_ht);

            sr.Close();
            bi_input.Close();
        }

        // Ohan's new code to load buildings
        private void LoadBuildings(float factor)
        {
            buildings = new List<TVMesh>();
            buildingsBig = new List<TVMesh>();

            FileStream file = new FileStream("manhattanville.config", FileMode.Open, FileAccess.Read);
            StreamReader sr = new StreamReader(file);

            String s = "", dir = "";
            float scale = 1, zRot, x, y, z;
            String[] chunks;
            int count = 0;
            char[] seps = { ' ' };
            D3DVECTOR min = new D3DVECTOR(), max = new D3DVECTOR();
            try
            {
                while (!sr.EndOfStream)
                {
                    s = sr.ReadLine();
                    if (s[0] == '$')
                        dir = s.Substring(1);
                    else if (s[0] == '%')
                        scale = (float)Double.Parse(s.Substring(1));
                    else if (s[0] != '#' && s.Length > 0)
                    {
                        chunks = s.Split(seps);
                        TVMesh model = m_kScenegraph.CreateMeshBuilder(chunks[0]);
                        model.Load3DSMesh(dir + chunks[0] + ".3ds", false, false, true, true, true);
                        model.ComputeBoundingVolumes();

                        zRot = (float)Double.Parse(chunks[1]);
                        x = (float)Double.Parse(chunks[2]);
                        y = (float)Double.Parse(chunks[3]);
                        z = (float)Double.Parse(chunks[4]);
                        model.ScaleMesh(scale, scale, scale);
                        model.SetRotation(0, 0, (float)(zRot * Math.PI / 180));
                        model.GetBoundingBox(ref min, ref max, false);
                        model.SetPosition(x, y, -max.z + z * factor);
                        model.EnableFrustumCulling(false);
                        TVMesh modelBig = model.DuplicateMesh(model.GetMeshName()+"Big");
                        modelBig.EnableFrustumCulling(false);

                        buildingHash.Add(chunks[0], model);
                        buildingBigHash.Add(chunks[0], modelBig);
                        buildings.Add(model);
                        buildingsBig.Add(modelBig);
                        origin.AddChild(ref model);
                        originBig.AddChild(ref modelBig);

                        count++;
                    }
                }
            }
            catch (Exception)
            {
                //MessageBox.Show("manhattanville.config has wrong format: " + s);
            }

            sr.Close();
            file.Close();
        }

        // Generate a 3D terrain of manhattanville
        private void GenerateTerrain(float factor)
        {
            float y_gap = 9.35f / 6;
            float x_gap = 5.55f / 4;
            float tu_gap = 1.0f / 6;
            float tv_gap = 1.0f / 4;
            TVMesh terrain = m_kScenegraph.CreateMeshBuilder("Terrain");

            float[,] terrain_heights = new float[,] { { 28, 48, 57, 66, 68 }, { 20, 29, 43, 53, 58 }, { 16, 24, 32, 40, 46 },
                { 13, 18, 25, 29, 35 }, { 10, 13, 17, 21, 26 }, { 14, 15, 18, 23, 23 }, { 44, 35, 32, 26, 24 } };

            for (int i = 0; i < 7; i++)
                for (int j = 0; j < 5; j++)
                    terrain_heights[i, j] *= factor;

            int map_texture = m_kTexFactory.LoadTexture("manhattanville_map.jpg", "Terrain Map", -1, -1,
                CONST_TV_COLORKEY.TV_COLORKEY_NO, false, false);

            // Create the terrain 
            terrain.AddFace(map_texture, false);
            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 6; j++)
                {
                    terrain.AddVertex(j * y_gap, i * x_gap, terrain_heights[j, i], m_kGlobals.RGBA(1f, 0f, 0f, 1f), j * tu_gap, 1 - i * tv_gap, 0f, 0f, 1f, false, 0, 0);
                    terrain.AddVertex(j * y_gap, (i + 1) * x_gap, terrain_heights[j, i + 1], m_kGlobals.RGBA(1f, 0f, 0f, 1f), j * tu_gap, 1 - (i + 1) * tv_gap, 0f, 0f, 1f, false, 0, 0);
                    terrain.AddVertex((j + 1) * y_gap, i * x_gap, terrain_heights[j + 1, i], m_kGlobals.RGBA(1f, 0f, 0f, 1f), (j + 1) * tu_gap, 1 - i * tv_gap, 0f, 0f, 1f, false, 0, 0);

                    terrain.AddVertex((j + 1) * y_gap, (i + 1) * x_gap, terrain_heights[j + 1, i + 1], m_kGlobals.RGBA(1f, 0f, 0f, 1f), (j + 1) * tu_gap, 1 - (i + 1) * tv_gap, 0f, 0f, 1f, false, 0, 0);
                    terrain.AddVertex(j * y_gap, (i + 1) * x_gap, terrain_heights[j, i + 1], m_kGlobals.RGBA(1f, 0f, 0f, 1f), j * tu_gap, 1 - (i + 1) * tv_gap, 0f, 0f, 1f, false, 0, 0);
                    terrain.AddVertex((j + 1) * y_gap, i * x_gap, terrain_heights[j + 1, i], m_kGlobals.RGBA(1f, 0f, 0f, 1f), (j + 1) * tu_gap, 1 - i * tv_gap, 0f, 0f, 1f, false, 0, 0);
                }
            }

            // Create the skirf
            terrain.AddFace(0, false);
            for (int i = 0; i < 4; i++)
            {
                terrain.AddVertex(0, i * x_gap, 0, m_kGlobals.RGBA(1f, 0f, 0f, 1f), 0, 0, 0f, 0f, 1f, false, 0, 0);
                terrain.AddVertex(0, i * x_gap, terrain_heights[0, i], m_kGlobals.RGBA(0f, 1f, 0f, 1f), 0, 0, 0f, 0f, 1f, false, 0, 0);
                terrain.AddVertex(0, (i + 1) * x_gap, terrain_heights[0, i + 1], m_kGlobals.RGBA(0f, 0f, 1f, 1f), 0, 0, 0f, 0f, 1f, false, 0, 0);

                terrain.AddVertex(0, (i + 1) * x_gap, 0, m_kGlobals.RGBA(1f, 0f, 0f, 1f), 0, 0, 0f, 0f, 1f, false, 0, 0);
                terrain.AddVertex(0, i * x_gap, 0, m_kGlobals.RGBA(1f, 0f, 0f, 1f), 0, 0, 0f, 0f, 1f, false, 0, 0);
                terrain.AddVertex(0, (i + 1) * x_gap, terrain_heights[0, i + 1], m_kGlobals.RGBA(0f, 0f, 1f, 1f), 0, 0, 0f, 0f, 1f, false, 0, 0);

                terrain.AddVertex(6 * y_gap, i * x_gap, 0, m_kGlobals.RGBA(1f, 0f, 0f, 1f), 0, 0, 0f, 0f, 1f, false, 0, 0);
                terrain.AddVertex(6 * y_gap, i * x_gap, terrain_heights[6, i], m_kGlobals.RGBA(0f, 1f, 0f, 1f), 0, 0, 0f, 0f, 1f, false, 0, 0);
                terrain.AddVertex(6 * y_gap, (i + 1) * x_gap, terrain_heights[6, i + 1], m_kGlobals.RGBA(0f, 0f, 1f, 1f), 0, 0, 0f, 0f, 1f, false, 0, 0);

                terrain.AddVertex(6 * y_gap, (i + 1) * x_gap, 0, m_kGlobals.RGBA(1f, 0f, 0f, 1f), 0, 0, 0f, 0f, 1f, false, 0, 0);
                terrain.AddVertex(6 * y_gap, i * x_gap, 0, m_kGlobals.RGBA(1f, 0f, 0f, 1f), 0, 0, 0f, 0f, 1f, false, 0, 0);
                terrain.AddVertex(6 * y_gap, (i + 1) * x_gap, terrain_heights[6, i + 1], m_kGlobals.RGBA(0f, 0f, 1f, 1f), 0, 0, 0f, 0f, 1f, false, 0, 0);
            }

            for (int j = 0; j < 6; j++)
            {
                terrain.AddVertex(j * y_gap, 0, 0, m_kGlobals.RGBA(1f, 0f, 0f, 1f), 0, 0, 0f, 0f, 1f, false, 0, 0);
                terrain.AddVertex(j * y_gap, 0, terrain_heights[j, 0], m_kGlobals.RGBA(0f, 1f, 0f, 1f), 0, 0, 0f, 0f, 1f, false, 0, 0);
                terrain.AddVertex((j + 1) * y_gap, 0, terrain_heights[j + 1, 0], m_kGlobals.RGBA(0f, 0f, 1f, 1f), 0, 0, 0f, 0f, 1f, false, 0, 0);

                terrain.AddVertex((j + 1) * y_gap, 0, 0, m_kGlobals.RGBA(1f, 0f, 0f, 1f), 0, 0, 0f, 0f, 1f, false, 0, 0);
                terrain.AddVertex(j * y_gap, 0, 0, m_kGlobals.RGBA(1f, 0f, 0f, 1f), 0, 0, 0f, 0f, 1f, false, 0, 0);
                terrain.AddVertex((j + 1) * y_gap, 0, terrain_heights[j + 1, 0], m_kGlobals.RGBA(0f, 0f, 1f, 1f), 0, 0, 0f, 0f, 1f, false, 0, 0);

                terrain.AddVertex(j * y_gap, 4 * x_gap, 0, m_kGlobals.RGBA(1f, 0f, 0f, 1f), 0, 0, 0f, 0f, 1f, false, 0, 0);
                terrain.AddVertex(j * y_gap, 4 * x_gap, terrain_heights[j, 4], m_kGlobals.RGBA(0f, 1f, 0f, 1f), 0, 0, 0f, 0f, 1f, false, 0, 0);
                terrain.AddVertex((j + 1) * y_gap, 4 * x_gap, terrain_heights[j + 1, 4], m_kGlobals.RGBA(0f, 0f, 1f, 1f), 0, 0, 0f, 0f, 1f, false, 0, 0);

                terrain.AddVertex((j + 1) * y_gap, 4 * x_gap, 0, m_kGlobals.RGBA(1f, 0f, 0f, 1f), 0, 0, 0f, 0f, 1f, false, 0, 0);
                terrain.AddVertex(j * y_gap, 4 * x_gap, 0, m_kGlobals.RGBA(1f, 0f, 0f, 1f), 0, 0, 0f, 0f, 1f, false, 0, 0);
                terrain.AddVertex((j + 1) * y_gap, 4 * x_gap, terrain_heights[j + 1, 4], m_kGlobals.RGBA(0f, 0f, 1f, 1f), 0, 0, 0f, 0f, 1f, false, 0, 0);
            }

            terrain.SetPosition(7f, 2.31f, 0f);
            terrain.SetRotation(0, 0, (float)Math.PI / 2);

            origin.AddChild(ref terrain);
        }
    }
}
